package cn.iocoder.yudao.module.system.service.exam;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.system.config.ExamTestProperties;
import cn.iocoder.yudao.module.system.controller.admin.exam.vo.*;
import cn.iocoder.yudao.module.system.enums.ErrorCodeConstants;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 测评系统 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Slf4j
public class ExamTestServiceImpl implements ExamTestService {

    @Resource
    private ExamTestApiService examTestApiService;

    @Resource
    private ExamDataService examDataService;

    @Resource
    private ExamTestProperties examTestProperties;

    @Override
    public List<ExamTestQuestionVO> getTestQuestions(String tbl) {
        // 从配置中获取appKey
        String appKey = examTestProperties.getAppKeyByTbl(tbl);
        if (StrUtil.isBlank(appKey)) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.EXAM_TEST_APP_KEY_REQUIRED);
        }

        // 先尝试从数据库获取
        List<ExamTestQuestionVO> cachedQuestions = examDataService.getQuestions(tbl);
        if (cachedQuestions != null && !cachedQuestions.isEmpty()) {
            log.info("从数据库获取测评题列表，共{}道题", cachedQuestions.size());
            return cachedQuestions;
        }

        // 数据库中没有数据，调用第三方API获取
        String apiResponse = examTestApiService.fetchTestQuestionsFromApi(tbl);
        if (StrUtil.isBlank(apiResponse)) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.EXAM_TEST_API_CALL_FAILED);
        }

        // 解析API响应
        try {
            JSONObject responseJson = JSON.parseObject(apiResponse);

            // 检查响应状态
            Integer code = responseJson.getInteger("code");
            if (code == null || code != 10000) {
                String msg = responseJson.getString("msg");
                log.error("API返回错误，code: {}, msg: {}", code, msg);
                throw ServiceExceptionUtil.exception(ErrorCodeConstants.EXAM_TEST_API_ERROR, msg);
            }

            // 获取数据列表
            JSONObject data = responseJson.getJSONObject("data");
            if (data == null) {
                return new ArrayList<>();
            }

            JSONArray dataList = data.getJSONArray("dataList");
            if (dataList == null || dataList.isEmpty()) {
                return new ArrayList<>();
            }

            // 转换为VO对象
            List<ExamTestQuestionVO> questions = new ArrayList<>();
            for (int i = 0; i < dataList.size(); i++) {
                JSONObject item = dataList.getJSONObject(i);
                ExamTestQuestionVO question = parseQuestionFromJson(item);
                questions.add(question);
            }

            // 保存到数据库
            examDataService.saveQuestions(appKey, tbl, questions);

            log.info("成功获取并保存测评题列表，共{}道题", questions.size());
            return questions;

        } catch (Exception e) {
            log.error("解析测评题列表API响应失败", e);
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.EXAM_TEST_PARSE_ERROR);
        }
    }

    @Override
    public ExamTestInfoVO getTestInfo(String tbl) {
        // 从配置中获取appKey
        String appKey = examTestProperties.getAppKeyByTbl(tbl);
        if (StrUtil.isBlank(appKey)) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.EXAM_TEST_APP_KEY_REQUIRED);
        }

        // 先尝试从数据库获取
        ExamTestInfoVO cachedTestInfo = examDataService.getTestInfo(tbl);
        if (cachedTestInfo != null) {
            log.info("从数据库获取测评信息");
            return cachedTestInfo;
        }

        // 数据库中没有数据，调用第三方API获取
        String apiResponse = examTestApiService.fetchTestInfoFromApi(tbl);
        if (StrUtil.isBlank(apiResponse)) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.EXAM_TEST_API_CALL_FAILED);
        }

        // 解析API响应
        try {
            JSONObject responseJson = JSON.parseObject(apiResponse);

            // 检查响应状态
            Integer code = responseJson.getInteger("code");
            if (code == null || code != 10000) {
                String msg = responseJson.getString("msg");
                log.error("API返回错误，code: {}, msg: {}", code, msg);
                throw ServiceExceptionUtil.exception(ErrorCodeConstants.EXAM_TEST_API_ERROR, msg);
            }

            // 获取数据
            JSONObject data = responseJson.getJSONObject("data");
            if (data == null) {
                throw ServiceExceptionUtil.exception(ErrorCodeConstants.EXAM_TEST_NO_DATA);
            }

            // 转换为VO对象
            ExamTestInfoVO testInfo = parseTestInfoFromJson(data);

            // 保存到数据库
            examDataService.saveTestInfo(appKey, tbl, testInfo);

            log.info("成功获取并保存测评信息");
            return testInfo;

        } catch (Exception e) {
            log.error("解析测评信息API响应失败", e);
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.EXAM_TEST_PARSE_ERROR);
        }
    }

    @Override
    public ExamTestReportVO getTestReport(String tbl, String reportType, String answer, String isAllAnswer) {
        // 从配置中获取appKey
        String appKey = examTestProperties.getAppKeyByTbl(tbl);
        if (StrUtil.isBlank(appKey)) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.EXAM_TEST_APP_KEY_REQUIRED);
        }

        // 验证答案
        if (StrUtil.isBlank(answer)) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.EXAM_TEST_ANSWER_REQUIRED);
        }

        // 调用第三方API获取数据
        String apiResponse = examTestApiService.fetchTestReportFromApi(tbl, reportType, answer, isAllAnswer);
        if (StrUtil.isBlank(apiResponse)) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.EXAM_TEST_API_CALL_FAILED);
        }

        // 解析API响应
        try {
            JSONObject responseJson = JSON.parseObject(apiResponse);
            
            // 检查响应状态
            Integer code = responseJson.getInteger("code");
            if (code == null || code != 10000) {
                String msg = responseJson.getString("msg");
                log.error("API返回错误，code: {}, msg: {}" , code, msg);
                throw ServiceExceptionUtil.exception(ErrorCodeConstants.EXAM_TEST_API_ERROR, msg);
            }

            // 获取数据
            JSONObject data = responseJson.getJSONObject("data");
            if (data == null) {
                throw ServiceExceptionUtil.exception(ErrorCodeConstants.EXAM_TEST_NO_DATA);
            }

            // 转换为VO对象
            ExamTestReportVO report = parseTestReportFromJson(data);
            
            log.info("成功获取测评报告");
            return report;

        } catch (Exception e) {
            log.error("解析测评报告API响应失败", e);
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.EXAM_TEST_PARSE_ERROR);
        }
    }

    @Override
    public ExamTestReportVO submitAnswers(ExamAnswerSubmitReqVO submitReqVO) {
        // 从配置中获取appKey
        String appKey = examTestProperties.getAppKeyByTbl(submitReqVO.getTbl());

        // 构建答案字符串
        StringBuilder answerBuilder = new StringBuilder();
        for (int i = 0; i < submitReqVO.getAnswers().size(); i++) {
            ExamAnswerSubmitReqVO.ExamAnswerItemVO answerItem = submitReqVO.getAnswers().get(i);
            if (i > 0) {
                answerBuilder.append(",");
            }
            answerBuilder.append(answerItem.getDetailsId()).append("-").append(answerItem.getAnswerIndex());
        }
        String answer = answerBuilder.toString();

        // 先检查缓存中是否已有相同答题组合的报告
        ExamTestReportVO cachedReport = examDataService.getCachedTestReport(
                appKey, submitReqVO.getTbl(), submitReqVO.getReportType(), answer, submitReqVO.getIsAllAnswer());

        ExamTestReportVO report;
        boolean isFromCache = false;

        if (cachedReport != null) {
            // 使用缓存的报告
            report = cachedReport;
            isFromCache = true;
            log.info("使用缓存的测评报告，避免重复调用外部API");
        } else {
            // 缓存中没有，调用外部API获取报告
            log.info("缓存中未找到相同答题组合的报告，调用外部API获取");
            report = getTestReport(submitReqVO.getTbl(),
                    submitReqVO.getReportType(), answer, submitReqVO.getIsAllAnswer());
        }

        // 保存测评报告和答题记录到数据库
        // 注意：这里需要用户ID，可以从SecurityFrameworkUtils获取当前登录用户
        Long userId = getCurrentUserId();
        if (userId != null) {
            String testBatchNo = generateTestBatchNo();

            // 保存答题记录
            examDataService.saveUserAnswers(userId, testBatchNo, submitReqVO);

            // 只有当报告不是来自缓存时，才保存新的报告记录
            // 如果是来自缓存的，我们仍然为当前用户创建一个报告记录，但标记为引用缓存
            examDataService.saveTestReport(userId, appKey, submitReqVO.getTbl(),
                    testBatchNo, submitReqVO, report);

            log.info("成功保存用户测评记录，userId: {}, testBatchNo: {}, 报告来源: {}",
                    userId, testBatchNo, isFromCache ? "缓存" : "外部API");
        }

        return report;
    }

    /**
     * 从JSON解析题目信息
     */
    private ExamTestQuestionVO parseQuestionFromJson(JSONObject json) {
        ExamTestQuestionVO question = new ExamTestQuestionVO();
        question.setDetailsId(json.getLong("detailsId"));
        question.setTbl(json.getString("tbl"));
        question.setClassifys(json.getString("classifys"));
        question.setTitle(json.getString("title"));
        question.setDetails(json.getString("details"));
        question.setMarks(json.getString("marks"));
        question.setFormat(json.getString("format"));

        // 解析选项
        String details = json.getString("details");
        if (StrUtil.isNotBlank(details)) {
            List<ExamTestOptionVO> options = parseOptionsFromDetails(details);
            question.setOptions(options);
        }

        return question;
    }

    /**
     * 从details字符串解析选项
     */
    private List<ExamTestOptionVO> parseOptionsFromDetails(String details) {
        List<ExamTestOptionVO> options = new ArrayList<>();
        if (StrUtil.isBlank(details)) {
            return options;
        }

        String[] optionArray = details.split(",");
        for (int i = 0; i < optionArray.length; i++) {
            String optionStr = optionArray[i];
            String[] parts = optionStr.split("___");
            
            ExamTestOptionVO option = new ExamTestOptionVO();
            option.setIndex(i);
            option.setContent(parts.length > 0 ? parts[0] : "");
            option.setScore(parts.length > 1 ? parts[1] : "");
            option.setOptionKey(String.valueOf((char) ('A' + i))); // A, B, C, D...
            
            options.add(option);
        }

        return options;
    }

    /**
     * 从JSON解析测评信息
     */
    private ExamTestInfoVO parseTestInfoFromJson(JSONObject json) {
        ExamTestInfoVO testInfo = new ExamTestInfoVO();
        testInfo.setName(json.getString("name"));
        testInfo.setQuestionNum(json.getString("questionNum"));
        testInfo.setExamTotalTime(json.getString("examTotalTime"));
        testInfo.setExamTips(json.getString("examTips"));
        testInfo.setPoster(json.getString("poster"));
        testInfo.setIntroduceImages(json.getString("introduceImages"));
        testInfo.setAdvertiseTitle(json.getString("advertiseTitle"));
        testInfo.setIntroduce(json.getString("introduce"));
        testInfo.setStandardIntroduce(json.getString("standardIntroduce"));
        testInfo.setScoreFormat(json.getString("scoreFormat"));
        
        // 解析fieldOptions
        JSONArray fieldOptions = json.getJSONArray("fieldOptions");
        if (fieldOptions != null) {
            testInfo.setFieldOptions((List<Map<String, Object>>) (List<?>) fieldOptions.toJavaList(Map.class));
        }

        JSONArray fieldOptions2 = json.getJSONArray("fieldOptions2");
        if (fieldOptions2 != null) {
            testInfo.setFieldOptions2((List<Map<String, Object>>) (List<?>) fieldOptions2.toJavaList(Map.class));
        }

        return testInfo;
    }

    /**
     * 从JSON解析测评报告
     */
    private ExamTestReportVO parseTestReportFromJson(JSONObject json) {
        ExamTestReportVO report = new ExamTestReportVO();
        
        // 解析fieldOptions
        JSONArray fieldOptions = json.getJSONArray("fieldOptions");
        if (fieldOptions != null) {
            report.setFieldOptions((List<Map<String, Object>>) (List<?>) fieldOptions.toJavaList(Map.class));
        }

        JSONArray fieldOptions2 = json.getJSONArray("fieldOptions2");
        if (fieldOptions2 != null) {
            report.setFieldOptions2((List<Map<String, Object>>) (List<?>) fieldOptions2.toJavaList(Map.class));
        }

        // 设置所有字段
        report.setReportType(json.getString("reportType"));
        report.setReportTypeInfo(json.getString("reportTypeInfo"));
        report.setEnglish(json.getString("English"));
        report.setQuestionNum(json.getString("questionNum"));
        report.setFullScore(json.getString("fullScore"));
        report.setAverageScore(json.getString("averageScore"));
        report.setNormalRange(json.getString("normalRange"));
        report.setScore(json.getString("score"));
        report.setScoreFormat(json.getString("scoreFormat"));
        report.setScoreFormatExplain(json.getString("scoreFormatExplain"));
        report.setScoreIsNormal(json.getString("scoreIsNormal"));
        report.setMyScoreArr(json.getString("myScoreArr"));
        report.setMyScoreDetailsArr(json.getString("myScoreDetailsArr"));
        report.setIntroduce(json.getString("introduce"));
        report.setProfile(json.getString("profile"));
        report.setDevelopment(json.getString("development"));
        report.setOrigin(json.getString("origin"));
        report.setInstructions(json.getString("instructions"));
        report.setInfluenceFactor(json.getString("influenceFactor"));
        report.setAverageValue(json.getString("averageValue"));
        report.setDispute(json.getString("dispute"));
        report.setAppraiseName(json.getString("appraiseName"));
        report.setAppraise(json.getString("appraise"));
        report.setDescription(json.getString("description"));
        report.setConceptualDescription(json.getString("conceptualDescription"));
        report.setDescriptionWords(json.getString("descriptionWords"));
        report.setAnalyse(json.getString("analyse"));
        report.setImprove(json.getString("improve"));
        report.setSignificance(json.getString("significance"));
        report.setApplication(json.getString("application"));
        report.setEffect(json.getString("effect"));
        report.setSelfImprovement(json.getString("selfImprovement"));
        report.setCase_(json.getString("case"));
        report.setBusinessCase(json.getString("businessCase"));
        report.setEmployeeCase(json.getString("employeeCase"));
        report.setPeoplePercentage(json.getString("peoplePercentage"));
        report.setAgeDistribution(json.getString("ageDistribution"));
        report.setTypeRelationship(json.getString("typeRelationship"));
        report.setPersonalityType(json.getString("personalityType"));
        report.setPersonalityType2(json.getString("personalityType2"));
        report.setDimension(json.getString("dimension"));
        report.setRegionalDivision(json.getString("regionalDivision"));
        report.setAdvantage(json.getString("advantage"));
        report.setDisadvantage(json.getString("disadvantage"));
        report.setShortage(json.getString("shortage"));
        report.setFeature(json.getString("feature"));
        report.setPersonalityFeature(json.getString("personalityFeature"));
        report.setPersonalitySublimationDeterioration(json.getString("personalitySublimationDeterioration"));
        report.setAttentionPoints(json.getString("attentionPoints"));
        report.setPerformance(json.getString("performance"));
        report.setTypicalPerformance(json.getString("typicalPerformance"));
        report.setDisposition(json.getString("disposition"));
        report.setPersonalityCharacteristics(json.getString("personalityCharacteristics"));
        report.setPersonalityAalysis(json.getString("personalityAalysis"));
        report.setCharacterAnalysis(json.getString("characterAnalysis"));
        report.setCharacterSketch(json.getString("characterSketch"));
        report.setNeurologicalCharacteristics(json.getString("neurologicalCharacteristics"));
        report.setPsychologicalCharacteristics(json.getString("psychologicalCharacteristics"));
        report.setMainCharacteristics(json.getString("mainCharacteristics"));
        report.setTendentiousOrder(json.getString("tendentiousOrder"));
        report.setSuitableFields(json.getString("suitableFields"));
        report.setSuitableJob(json.getString("suitableJob"));
        report.setReferenceMajor(json.getString("referenceMajor"));
        report.setBodyLanguage(json.getString("bodyLanguage"));
        report.setConversationStyle(json.getString("conversationStyle"));
        report.setCommunicationMethods(json.getString("communicationMethods"));
        report.setCommunicationMethods2(json.getString("communicationMethods2"));
        report.setBreakthroughPoint(json.getString("breakthroughPoint"));
        report.setLifestyle(json.getString("lifestyle"));
        report.setInterpersonalRelationship(json.getString("interpersonalRelationship"));
        report.setStyle(json.getString("style"));
        report.setWorkStyleBehaviors(json.getString("workStyleBehaviors"));
        report.setLeadershipModel(json.getString("leadershipModel"));
        report.setRroblemSolvingMode(json.getString("rroblemSolvingMode"));
        report.setAtWork(json.getString("atWork"));
        report.setWorkEnvironmentOrientation(json.getString("workEnvironmentOrientation"));
        report.setTeamContribution(json.getString("teamContribution"));
        report.setEmotion(json.getString("emotion"));
        report.setFear(json.getString("fear"));
        report.setBasicFear(json.getString("basicFear"));
        report.setDesire(json.getString("desire"));
        report.setDesireTrait(json.getString("desireTrait"));
        report.setBasicDesire(json.getString("basicDesire"));
        report.setBasicDrowsiness(json.getString("basicDrowsiness"));
        report.setEmotionsTerms(json.getString("emotionsTerms"));
        report.setMainSubtypes(json.getString("mainSubtypes"));
        report.setGrowthEnvironment(json.getString("growthEnvironment"));
        report.setHealthStatus(json.getString("healthStatus"));
        report.setTarget(json.getString("target"));
        report.setWorldView(json.getString("worldView"));
        report.setAttentionFocus(json.getString("attentionFocus"));
        report.setSelfProtectionMechanism(json.getString("selfProtectionMechanism"));
        report.setCorruptCustoms(json.getString("corruptCustoms"));
        report.setStrong(json.getString("strong"));
        report.setImprovingDiet(json.getString("ImprovingDiet"));

        return report;
    }

    /**
     * 获取当前登录用户ID
     */
    private Long getCurrentUserId() {
        try {
            return SecurityFrameworkUtils.getLoginUserId();
        } catch (Exception e) {
            log.warn("获取当前用户ID失败", e);
            return null;
        }
    }

    /**
     * 生成测试批次号
     */
    private String generateTestBatchNo() {
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String randomId = IdUtil.fastSimpleUUID().substring(0, 8);
        return "TEST_" + timestamp + "_" + randomId;
    }

}
